package com.campus.server;

import com.campus.common.type.BuyResult;
import com.campus.common.vo.*;
import com.campus.common.message.*;
//import com.campus.common.type.BuyResult;
import com.campus.server.service.*;

import java.io.*;
import java.net.Socket;
import java.net.SocketException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

public class ClientHandler implements Runnable {
    private Socket socket;

    private static final String IMAGE_DIR = "D:/shop_images";


    public ClientHandler(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try (
                ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
                ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
        ) {
            Object obj;
            while (!socket.isClosed() && (obj = in.readObject()) != null) {
                System.out.println("收到请求对象: " + obj.getClass());

                // 商店模块
                if (obj instanceof ShopRequest shopReq) {
                    handleShop(shopReq, out);
                }
                // 登录模块
                else if (obj instanceof LoginRequest loginReq) {
                    handleLogin(loginReq, out);
                }
                // 学生注册
                else if (obj instanceof StudentRegisterRequest studentReq) {
                    handleStudentRegister(studentReq, out);
                }
                // 教师注册
                else if (obj instanceof TeacherRegisterRequest teacherReq) {
                    handleTeacherRegister(teacherReq, out);
                }
                // 密码修改
                else if (obj instanceof PasswordChangeRequest pwdReq) {
                    handlePasswordChange(pwdReq, out);
                }
                // 图书馆
                else if (obj instanceof LibraryRequest libReq) {
                    handleLibrary(libReq, out);
                }
                // 银行
                else if (obj instanceof BankRequest bankReq) {
                    handleBank(bankReq, out);
                }
                // 学生课程模块
                else if (obj instanceof StudentCourseRequest stuCourseReq) {
                    StudentCourseResponse resp = new CourseService().handle(stuCourseReq);
                    out.writeObject(resp);
                    out.flush();
                }
                // 教师课程模块
                else if (obj instanceof TeacherCourseRequest teaCourseReq) {
                    TeacherCourseResponse resp = new CourseService().handle(teaCourseReq);
                    out.writeObject(resp);
                    out.flush();
                }
                // 管理员课程模块
                else if (obj instanceof AdminCourseRequest adminCourseReq) {
                    AdminCourseResponse resp = new CourseService().handle(adminCourseReq);
                    out.writeObject(resp);
                    out.flush();
                }
                //学生账号管理模块
                else if (obj instanceof StudentAccountManagementRequest studentAccountManagementReq) {
                    System.out.println("received");
                    handleStudentAccountManagement(studentAccountManagementReq, out);
                }
                //教师账号管理
                else if (obj instanceof TeacherAccountManagementRequest teacherAccountManagementReq) {
                    handleTeacherAccountManagement(teacherAccountManagementReq, out);
                }
                //管理员账号管理
                else if (obj instanceof AdminAccountManagementRequest adminAccountManagementReq) {
                    handleAdminAccountManagement(adminAccountManagementReq, out);
                }
                //图片加载
                else if (obj instanceof UploadImageRequest uploadReq) {
                    handleUploadImage(uploadReq, out);
                } 
                else if (obj instanceof GetImageRequest getReq) {
                    handleGetImage(getReq, out);
                }
                else if (obj instanceof StudentChangeInfoRequest studentChangeInfoReq) {
                    handleStudentRequest(studentChangeInfoReq, out);
                }
                else if (obj instanceof TeacherChangeInfoRequest teacherChangeInfoReq) {
                    handleTeacherRequest(teacherChangeInfoReq, out);
                }

                // 未知请求
                else {
                    System.out.println("收到未知对象: " + obj);
                }
            }
        } catch (EOFException e) {
            System.out.println("客户端已关闭连接");
        } catch (SocketException e) {
            System.out.println("客户端异常断开连接: " + e.getMessage());
        } catch (Exception e) {
            System.out.println("处理客户端请求时发生异常: " + e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                if (!socket.isClosed()) {
                    socket.close();
                    System.out.println("已关闭客户端socket");
                }
            } catch (IOException e) {
                System.out.println("关闭socket时出错: " + e.getMessage());
            }
            System.out.println("客户端处理线程结束");
        }
    }

    /** 以下方法与第一部分逻辑完全一致，仅增加了课程模块在 run() 中处理 */

    private void handleShop(ShopRequest req, ObjectOutputStream out) {
        ShopService shopService = new ShopService();
        ShopResponse resp;
        try {
            if ("list".equals(req.getAction())) {
                List<Product> products = shopService.listProducts();
                resp = new ShopResponse(true, "查询成功", products);
            } else if ("buy".equals(req.getAction())) {
                List<Integer> productIds = req.getProductId() > 0 ? List.of(req.getProductId()) : req.getProductIds();
                List<Integer> quantities = req.getProductId() > 0 ? List.of(req.getQuantity()) : req.getQuantities();
                BuyResult result = shopService.buyProducts(productIds, quantities, req.getUserId(), req.getPassword());

                boolean ok = result == BuyResult.SUCCESS;
                String msg = switch (result) {
                    case SUCCESS -> "购买成功";
                    case INSUFFICIENT_STOCK -> "库存不足，请调整购物车";
                    case INSUFFICIENT_BALANCE -> "余额不足，请先充值或调整购物车";
                    case INCORRECT_PASSWORD -> "密码错误";
                    default -> "购买失败";
                };
                resp = new ShopResponse(ok, msg, null);
                resp.setBuyResult(result);
                System.out.println("购买操作结果: " + result);

            } else if ("add".equals(req.getAction())) {
        	    boolean ok = shopService.addNewProduct(req.getProduct()); // 需要在 ShopService 中实现
        	    resp = new ShopResponse(ok, ok ? "添加成功" : "添加失败", null);
        	    System.out.println("新增商品结果: " + ok);
        	
            }  else if ("delete".equals(req.getAction())) {
                boolean ok = shopService.removeProduct(req.getProductId());
                resp = new ShopResponse(ok, ok ? "删除成功" : "删除失败", null);
                System.out.println("删除商品结果: " + ok);

            } else if ("update".equals(req.getAction())) {
                boolean ok = shopService.modifyProduct(req.getProduct());
                resp = new ShopResponse(ok, ok ? "更新成功" : "更新失败", null);
                System.out.println("修改商品结果: " + ok);

            } else if ("status".equals(req.getAction())) {
                boolean ok = shopService.setProductStatus(req.getProductId(), req.getProduct().getStatus());
                resp = new ShopResponse(ok, ok ? "状态修改成功" : "状态修改失败", null);
                System.out.println("修改商品状态结果: " + ok);
            
            } else if ("hot".equals(req.getAction())) {
                boolean ok = shopService.setProductHot(req.getProductId(), req.getProduct().getHot());
                resp = new ShopResponse(ok, ok ? "商品热卖修改成功" : "商品热卖修改失败", null);
                System.out.println("修改商品热卖结果: " + ok);
            
            } else if ("new".equals(req.getAction())) {
                boolean ok = shopService.setProductNew(req.getProductId(), req.getProduct().getNewP());
                resp = new ShopResponse(ok, ok ? "商品上新修改成功" : "商品上新修改失败", null);
                System.out.println("修改商品上新结果 " + ok);
            
            } else if ("expire".equals(req.getAction())) {
                boolean ok = shopService.setProductExpire(req.getProductId(), req.getProduct().getExpireSoon());
                resp = new ShopResponse(ok, ok ? "商品临期修改成功" : "商品临期修改失败", null);
                System.out.println("修改商品临期结果: " + ok);
            
            } else {
                resp = new ShopResponse(false, "未知操作", null);
            }
            out.writeObject(resp);
            out.flush();
        } catch (IOException e) {
            System.out.println("发送数据失败: " + e.getMessage());
        }
    }
    
    private void handleUploadImage(UploadImageRequest req, ObjectOutputStream out) {
        try {
            File dir = new File(IMAGE_DIR);
            if (!dir.exists()) dir.mkdirs();

            File file = new File(dir, req.getFileName());
            Files.write(file.toPath(), req.getImageData());

            out.writeObject(new UploadImageResponse(true, "上传成功"));
            out.flush();
        } catch (IOException e) {
            try {
                out.writeObject(new UploadImageResponse(false, "上传失败: " + e.getMessage()));
                out.flush();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    private void handleGetImage(GetImageRequest req, ObjectOutputStream out) {
        try {
            File file = new File(IMAGE_DIR, req.getFileName());
            if (file.exists()) {
                byte[] data = Files.readAllBytes(file.toPath());
                out.writeObject(new GetImageResponse(data));
            } else {
                out.writeObject(new GetImageResponse(null)); // 图片不存在
            }
            out.flush();
        } catch (IOException e) {
            try {
                out.writeObject(new GetImageResponse(null));
                out.flush();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    private void handleLogin(LoginRequest req, ObjectOutputStream out) {
        UserService userService = new UserService();
        boolean ok = userService.login(req.getUsername(), req.getPassword(), req.getRole());
        LoginResponse resp = new LoginResponse(ok, ok ? req.getUsername() : "用户名或密码错误");
        try { out.writeObject(resp); out.flush(); } catch (IOException e) { System.out.println(e.getMessage()); }
    }

    private void handleBank(BankRequest req, ObjectOutputStream out) {
        BankService bankService = new BankService();
        BankResponse resp;
        try {
            switch (req.getType()) {
                case "query" -> {
                    double balance = bankService.queryBalance(req.getUserId());
                    resp = new BankResponse(balance >= 0, balance >= 0 ? "查询成功" : "查询失败", balance);
                }
                case "recharge" -> resp = new BankResponse(bankService.recharge(req.getUserId(), req.getAmount(), req.getPassword()), "充值操作", -1);
                case "open" -> resp = new BankResponse(bankService.openAccount(req.getUserId(), req.getAmount(), req.getPassword()), "开户操作", -1);
                case "delete" -> resp = new BankResponse(bankService.deleteAccount(req.getUserId(), req.getPassword()), "销户操作", -1);
                case "transactions" -> {
                    List<BankTransaction> list = bankService.queryTransactions(req.getUserId());
                    resp = new BankResponse(true, "流水查询成功", -1, list);
                }
                default -> resp = new BankResponse(false, "未知操作", -1);
            }
            out.writeObject(resp);
            out.flush();
        } catch (IOException e) { System.out.println(e.getMessage()); }
    }

    private void handleStudentRegister(StudentRegisterRequest req, ObjectOutputStream out) {
        StudentService studentService = new StudentService();
        boolean ok = studentService.register(req.getUsername(), req.getPassword(), req.getStudent());
        try { out.writeObject(new StudentRegisterResponse(ok, ok ? "注册成功" : "注册失败")); out.flush(); } catch (IOException e) { System.out.println(e.getMessage()); }
    }

    private void handleTeacherRegister(TeacherRegisterRequest req, ObjectOutputStream out) {
        TeacherService teacherService = new TeacherService();
        boolean ok = teacherService.register(req.getUsername(), req.getPassword(), req.getTeacher());
        try { out.writeObject(new TeacherRegisterResponse(ok, ok ? "注册成功" : "注册失败")); out.flush(); } catch (IOException e) { System.out.println(e.getMessage()); }
    }

    private void handlePasswordChange(PasswordChangeRequest req, ObjectOutputStream out) {
        UserService userService = new UserService();
        boolean ok = userService.passwordChange(req.getUsername(), req.getPassword());
        try { out.writeObject(new PasswordChangeResponse(ok, ok ? "修改成功" : "修改失败")); out.flush(); } catch (IOException e) { System.out.println(e.getMessage()); }
    }

    private void handleLibrary(LibraryRequest req, ObjectOutputStream out) {
        LibraryService libraryService = new LibraryService();
        LibraryResponse resp;
        System.out.println("DEBUG: 收到图书馆请求，action: " + req.getAction());
        try {
            switch (req.getAction()) {
                case "list" -> resp = new LibraryResponse(true, "查询成功", libraryService.listBooks());
                case "borrow" -> {
                    boolean success = libraryService.borrowBook(req.getBookId(), req.getUsername());
                    String message = success ? "借书成功" : "借书失败";
                    resp = new LibraryResponse(success, message, null);
                }
                case "return" -> {
                    boolean success = libraryService.returnBook(req.getBookId(), req.getUsername());
                    String message = success ? "还书成功" : "还书失败";
                    resp = new LibraryResponse(success, message, null);
                }
                case "add" -> {
                    boolean success = libraryService.addBook(req.getBook());
                    String message = success ? "添加书籍成功" : "添加书籍失败";
                    resp = new LibraryResponse(success, message, null);
                }
                case "delete" -> {
                    boolean success = libraryService.deleteBook(req.getBookId());
                    String message = success ? "删除书籍成功" : "删除书籍失败";
                    resp = new LibraryResponse(success, message, null);
                }
                case "update" -> {
                    boolean success = libraryService.updateBook(req.getBook());
                    String message = success ? "更新书籍成功" : "更新书籍失败";
                    resp = new LibraryResponse(success, message, null);
                }
                case "getBorrowList" -> {
                    List<Book> books = libraryService.getUserBorrowedBooks(req.getUsername());
                    resp = new LibraryResponse(true, "查询成功", books);
                }
                case "getBorrowRecords" -> {
                    List<BorrowRecord> borrowRecords = libraryService.getUserBorrowRecords(req.getUsername());
                    resp = new LibraryResponse(true, "查询成功", borrowRecords, true);
                }
                case "getBorrowersById" -> {
                    List<BorrowRecord> borrowRecords = libraryService.getBookBorrowersById(req.getBookId());
                    resp = new LibraryResponse(true, "查询成功", borrowRecords,true);
                }
                case "searchByTitle" -> resp = new LibraryResponse(true, "搜索成功", libraryService.searchBooksByTitle(req.getSearchTitle()));
                case "searchByAuthor" -> resp = new LibraryResponse(true, "搜索成功", libraryService.searchBooksByAuthor(req.getSearchAuthor()));
                case "search" -> resp = new LibraryResponse(true, "搜索成功", libraryService.searchBooks(req.getSearchTitle(), req.getSearchAuthor()));
                case "searchByCategory" -> resp = new LibraryResponse(true, "搜索成功", libraryService.searchBooksByCategory(req.getCategory()));  // 新增
                case "getAllCategories" -> {
                    List<String> categories = libraryService.getAllCategories();

                    resp = new LibraryResponse(true, "查询成功", null);
                    resp.setBorrowers(categories);  // 借用borrowers字段返回类别列表
                }
                default -> resp = new LibraryResponse(false, "未知操作", null);
            }
            out.writeObject(resp);
            out.flush();
        } catch (IOException e) { System.out.println(e.getMessage()); }
    }


    private void handleStudentAccountManagement(StudentAccountManagementRequest req, ObjectOutputStream out) {
        StudentAccountMangementService studentAccountMangementService = new StudentAccountMangementService();
        StudentAccountManagementResponse resp;
        try {
            switch (req.getAction()) {
                case "list" -> resp = new StudentAccountManagementResponse(true,"查询成功",studentAccountMangementService.listStudents(),null);
                case "add" -> resp = new StudentAccountManagementResponse(studentAccountMangementService.addStudent(req.getStudent()),"新增操作",null,null);
                case "delete" -> resp = new StudentAccountManagementResponse(studentAccountMangementService.deleteStudent(req.getStudentId()), "删除操作", null,null);
                case "update" -> resp = new StudentAccountManagementResponse(studentAccountMangementService.updateStudent(req.getStudent()), "更新操作", null,null);
                case "searchByTitle" -> resp = new StudentAccountManagementResponse(true, "搜索成功", studentAccountMangementService.searchStudentById(req.getSearchId()),null);
                case "getStudentById" -> {
                    resp = new StudentAccountManagementResponse(true,"找寻成功",null,studentAccountMangementService.getStudenstById(req.getSearchName()));
                }
                case "searchByAuthor" -> resp = new StudentAccountManagementResponse(true, "搜索成功", studentAccountMangementService.searchStudentsByName(req.getSearchName()),null);
                case "search" -> resp = new StudentAccountManagementResponse(true, "搜索成功", studentAccountMangementService.searchStudents(req.getSearchId(), req.getSearchName()),null);
                default -> resp = new StudentAccountManagementResponse(false, "未知操作", null,null);
            }
            out.writeObject(resp);
            out.flush();
        } catch (IOException e) { System.out.println(e.getMessage()); }

    }

    private void handleTeacherAccountManagement(TeacherAccountManagementRequest req, ObjectOutputStream out) {
        TeacherAccountManagementService teacherAccountManagementService = new TeacherAccountManagementService();
        TeacherAccountManagementResponse resp;
        try {
            switch (req.getAction()) {
                case "list" ->
                        resp = new TeacherAccountManagementResponse(true, "查询成功", teacherAccountManagementService.listTeachers(),null);
                case "add" ->
                        resp = new TeacherAccountManagementResponse(teacherAccountManagementService.addTeacher(req.getTeacher()), "新增操作", null,null);
                case "delete" ->
                        resp = new TeacherAccountManagementResponse(teacherAccountManagementService.deleteTeacher(req.getTeacherId()), "删除操作", null,null);
                case "update" ->
                        resp = new TeacherAccountManagementResponse(teacherAccountManagementService.updateTeacher(req.getTeacher()), "更新操作", null,null);
                case "searchByTitle" ->
                        resp = new TeacherAccountManagementResponse(true, "搜索成功", teacherAccountManagementService.searchTeacherById(req.getSearchId()),null);
                case "getTeacherById" -> {
                    resp = new TeacherAccountManagementResponse(true,"找寻成功",null,teacherAccountManagementService.getTeacherById(req.getSearchName()));
                }
                case "searchByAuthor" ->
                        resp = new TeacherAccountManagementResponse(true, "搜索成功", teacherAccountManagementService.searchTeachersByName(req.getSearchName()),null);
                case "search" ->
                        resp = new TeacherAccountManagementResponse(true, "搜索成功", teacherAccountManagementService.searchTeachers(req.getSearchId(), req.getSearchName()),null);
                default -> resp = new TeacherAccountManagementResponse(false, "未知操作", null,null);
            }
            out.writeObject(resp);
            out.flush();
        } catch (IOException e) { System.out.println(e.getMessage()); }
    }

    private void handleAdminAccountManagement(AdminAccountManagementRequest req, ObjectOutputStream out) {
        AdminAccountManagementService adminAccountManagementService = new AdminAccountManagementService();
        AdminAccountManagementResponse resp;
        try {
            switch (req.getAction()) {
                case "list" ->
                        resp = new AdminAccountManagementResponse(true, "查询成功", adminAccountManagementService.listAdmins());
                case "add" ->
                        resp = new AdminAccountManagementResponse(adminAccountManagementService.addAdmin(req.getAdmin()), "新增操作", null);
                case "delete" ->
                        resp = new AdminAccountManagementResponse(adminAccountManagementService.deleteAdmin(req.getAdminId()), "删除操作", null);
                case "search" ->
                        resp = new AdminAccountManagementResponse(true, "搜索成功", adminAccountManagementService.searchAdmins(req.getSearchId(), req.getSearchName()));
                default -> resp = new AdminAccountManagementResponse(false, "未知操作", null);
            }
            out.writeObject(resp);
            out.flush();
        } catch (IOException e) { System.out.println(e.getMessage()); }
    }
    private void handleStudentRequest(StudentChangeInfoRequest req, ObjectOutputStream out) {
        StudentService studentService = new StudentService();
        StudentChangeInfoResponse resp;
        try {
            switch (req.getAction()) {
                case "add" ->
                        resp = new StudentChangeInfoResponse(studentService.addStudentRequest(req.getStudentId(), req.getContactInfo(), req.getOldContactInfo()), "请求结果", null);
                case "delete" ->
                        resp = new StudentChangeInfoResponse(studentService.deleteStudentRequest(req.getStudentId(), req.getContactInfo()), "请求结果", null);
                case "list" -> {
                    resp = new StudentChangeInfoResponse(true, "", studentService.listRequests());
                }
                case "update" -> {
                    resp = new StudentChangeInfoResponse(studentService.upDateStudent(req.getStudentId(), req.getContactInfo()), "", null);
                }
                default -> resp = new StudentChangeInfoResponse(false, "未知操作", null);

            }
            out.writeObject(resp);
            out.flush();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void handleTeacherRequest(TeacherChangeInfoRequest req, ObjectOutputStream out) {
        TeacherService  teacherService= new TeacherService();
        TeacherChangeInfoResponse resp;
        try {
            switch (req.getAction()) {
                case "add" ->
                        resp = new TeacherChangeInfoResponse(teacherService.addTeacherRequest(req.getTeacherId(), req.getContactInfo(), req.getOldContactInfo()),"请求结果",null);
                case "delete" ->
                        resp = new TeacherChangeInfoResponse(teacherService.deleteTeacherRequest(req.getTeacherId(), req.getContactInfo()),"请求结果",null);
                case "list" ->{
                    resp = new TeacherChangeInfoResponse(true,"",teacherService.listRequests());
                }
                case "update" ->{
                    resp = new TeacherChangeInfoResponse(teacherService.upDateTeacher(req.getTeacherId(),req.getContactInfo()),"",null);
                }
                default -> resp = new TeacherChangeInfoResponse(false, "未知操作",null);

            }
            out.writeObject(resp);
            out.flush();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
